package top.jacktgq.wavelet;

import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jb2011.lnf.beautyeye.ch3_button.BEButtonUI;
import org.jb2011.lnf.beautyeye.ch3_button.BEButtonUI.NormalColor;

import top.jacktgq.utils.IconUtils;
import top.jacktgq.utils.custom_controls.image.CandyImageView;
import top.jacktgq.utils.custom_controls.loading.CandyLoadingBarDialog;
import top.jacktgq.utils.custom_controls.style.GUIStysle;
import top.jacktgq.utils.custom_controls.toast.CandyToaster;
import top.jacktgq.utils.thread.CandyShortTask;

public class MainWindow extends JFrame{
	private CandyLoadingBarDialog candyLoadingBarDialog;
	private JTextField amplitudeField;
	private JTextField omegaField;
	private JTextField bField;
	private JTextField phaseField;
	private JTextField savePathField;
	private JButton btn_save;
	private JButton button;
	private JSpinner rowCountField;
	private JCheckBox checkbox1;
	private JCheckBox checkbox2;
	private JCheckBox checkbox3;
	private JCheckBox checkbox4;
	private JCheckBox checkbox5;
	private JCheckBox checkbox6;
	private JCheckBox checkbox7;
	private JCheckBox checkbox8;
	private JCheckBox checkbox9;
	private JCheckBox checkbox10;
	private JCheckBox checkbox11;
	private JCheckBox checkbox12;
	private JCheckBox checkbox13;
	private JCheckBox checkbox14;
	private JCheckBox checkbox15;
	private JCheckBox checkbox16;
	
	public MainWindow() {
		setTitle("小波分析测试样本生成器");
		GUIStysle.setAutoStyle();
		CandyImageView imageView = 
				new CandyImageView(new ImageIcon(MainWindow.class.getResource("/icons/bg.jpg")).getImage(), Color.gray, CandyImageView.FIT_XY);
		imageView.hoverStyle.scaleType = CandyImageView.FIT_XY;
		imageView.setLayout(null);
		
		JLabel titleLabel = new JLabel("小波分析测试样本生成器");
		titleLabel.setForeground(new Color(165, 42, 42));
		titleLabel.setHorizontalAlignment(SwingConstants.CENTER);
		titleLabel.setFont(new Font("宋体", Font.BOLD, 24));
		titleLabel.setSize(286, 41);
		titleLabel.setLocation(137, 20);
		imageView.add(titleLabel);
		
		getContentPane().add(imageView);
		
		JLabel label1 = new JLabel("A（振幅）");
		label1.setHorizontalAlignment(SwingConstants.RIGHT);
		label1.setFont(new Font("宋体", Font.PLAIN, 16));
		label1.setBounds(68, 110, 72, 35);
		imageView.add(label1);
		
		amplitudeField = new JTextField();
		amplitudeField.setFont(new Font("宋体", Font.PLAIN, 16));
		amplitudeField.setText("1");
		amplitudeField.setBounds(162, 113, 66, 28);
		imageView.add(amplitudeField);
		amplitudeField.setColumns(10);
		
		JLabel formulaLabel = new JLabel("<html>信号表达式：<span style='color:red'>f(x)=ASin[ω(x+a)]+b</span></html>");
		formulaLabel.setFont(new Font("宋体", Font.PLAIN, 16));
		formulaLabel.setBounds(137, 60, 266, 29);
		imageView.add(formulaLabel);
		
		JLabel label = new JLabel("ω（2π/周期）");
		label.setHorizontalAlignment(SwingConstants.RIGHT);
		label.setFont(new Font("宋体", Font.PLAIN, 16));
		label.setBounds(261, 110, 116, 35);
		imageView.add(label);
		
		omegaField = new JTextField();
		omegaField.setText("0.0314");
		omegaField.setFont(new Font("宋体", Font.PLAIN, 16));
		omegaField.setColumns(10);
		omegaField.setBounds(398, 113, 66, 28);
		imageView.add(omegaField);
		
		JLabel lblA = new JLabel("b（向上平移）");
		lblA.setHorizontalAlignment(SwingConstants.RIGHT);
		lblA.setFont(new Font("宋体", Font.PLAIN, 16));
		lblA.setBounds(271, 155, 104, 35);
		imageView.add(lblA);
		
		bField = new JTextField();
		bField.setText("0");
		bField.setFont(new Font("宋体", Font.PLAIN, 16));
		bField.setColumns(10);
		bField.setBounds(396, 158, 66, 28);
		imageView.add(bField);
		
		JLabel label_1 = new JLabel("a（相位）");
		label_1.setHorizontalAlignment(SwingConstants.RIGHT);
		label_1.setFont(new Font("宋体", Font.PLAIN, 16));
		label_1.setBounds(68, 155, 72, 35);
		imageView.add(label_1);
		
		phaseField = new JTextField();
		phaseField.setText("0");
		phaseField.setFont(new Font("宋体", Font.PLAIN, 16));
		phaseField.setColumns(10);
		phaseField.setBounds(162, 158, 66, 28);
		imageView.add(phaseField);
		
		JLabel label_2 = new JLabel("保存数据组数");
		label_2.setFont(new Font("宋体", Font.PLAIN, 16));
		label_2.setBounds(36, 200, 104, 35);
		imageView.add(label_2);
		
		rowCountField = new JSpinner();
		rowCountField.setFont(new Font("宋体", Font.PLAIN, 16));
		rowCountField.setModel(new SpinnerNumberModel(1000, 500, 2000, 100));
		rowCountField.setBounds(162, 204, 66, 27);
		imageView.add(rowCountField);
		
		savePathField = new JTextField();
		savePathField.setEditable(false);
		savePathField.setText("请选择样本保存的路径");
		savePathField.setFont(new Font("宋体", Font.PLAIN, 16));
		savePathField.setColumns(10);
		savePathField.setBounds(248, 203, 175, 28);
		imageView.add(savePathField);
		
		btn_save = new JButton("选择");
		btn_save.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				JFileChooser chooser = new JFileChooser();
				
				//设置模式：仅选择目录
				chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
				
				//显示对话框，并获取用户选择的结果
				int ret = chooser.showSaveDialog(MainWindow.this);
				if(ret == JFileChooser.APPROVE_OPTION) {
					//结果为要保存的文件
					File fileDir = chooser.getSelectedFile();
					savePathField.setText(fileDir.getAbsolutePath());
				}
			}
		});
		btn_save.setFont(new Font("宋体", Font.PLAIN, 16));
		btn_save.setBounds(449, 203, 72, 28);
		btn_save.setUI(new BEButtonUI().setNormalColor(NormalColor.blue));
		btn_save.setForeground(Color.white);
		imageView.add(btn_save);
		
		button = new JButton("产生样本");
		button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				new CandyShortTask() {
					private int rowCount;
					private String savePath;

					@Override
					protected void doInBackground() throws Exception {
						//先校验文本框是否有空的情况
						boolean passCheck =  checkTextField(amplitudeField, omegaField, phaseField, bField);
						if(!passCheck) {
							CandyToaster.show(MainWindow.this, "信号参数不能为空！", CandyToaster.ERROR);
							return;
						}

						//获取各个文本框中的值
						//振幅
						double amplitude = Double.parseDouble(amplitudeField.getText().trim());
						if(amplitude <= 0) {
							CandyToaster.show(MainWindow.this, "振幅须大于零！", CandyToaster.ERROR);
							return;
						}
						//哦米噶
						double omega = Double.parseDouble(omegaField.getText().trim());
						//相位
						double phase = Double.parseDouble(phaseField.getText().trim());
						//Y坐标平移量
						double b = Double.parseDouble(bField.getText().trim());
						//保存样本的路径
						savePath = savePathField.getText();
						if(savePath.equals("请选择样本保存的路径")) {
							CandyToaster.show(MainWindow.this, "请先选择样本保存的路径！", CandyToaster.ERROR);
							return;
						}
						//保存数据组数
						rowCount = (int) rowCountField.getValue();
						System.out.println("振幅：" + amplitude + 
										   "，哦米噶：" + omega + 
										   "，相位：" + phase + 
										   "，Y坐标平移量平移量：" + b + 
										   "，样本数据组数：" + rowCount + 
										   "，保存样本的路径：" + savePath);
						//根据参数代入公式产生原始样本保存到TXT文本中
						generateSampleByFormula(new GeneratePolicy(0), "原始样本数据", amplitude, omega, phase, b);
						//遍历check所有checkbox
						if(checkbox1.isSelected()) {
							generateSampleByFormula(new GeneratePolicy(1), "整体上移2倍后的样本数据", amplitude, omega, phase, b);
						}
						if(checkbox2.isSelected()) {
							generateSampleByFormula(new GeneratePolicy(2), "整体上移5倍后的样本数据", amplitude, omega, phase, b);
						}
						if(checkbox3.isSelected()) {
							generateSampleByFormula(new GeneratePolicy(3), "整体下移2倍后的样本数据", amplitude, omega, phase, b);
						}
						if(checkbox4.isSelected()) {
							generateSampleByFormula(new GeneratePolicy(4), "整体下移5倍后的样本数据", amplitude, omega, phase, b);
						}
						if(checkbox5.isSelected()) {
							generateSampleByFormula(new GeneratePolicy(5), "后5分之一上移2倍后的样本数据", amplitude, omega, phase, b);
						}
						if(checkbox6.isSelected()) {
							generateSampleByFormula(new GeneratePolicy(6), "后5分之一上移5倍后的样本数据", amplitude, omega, phase, b);
						}
						if(checkbox7.isSelected()) {
							generateSampleByFormula(new GeneratePolicy(7), "后5分之一下移2倍后的样本数据", amplitude, omega, phase, b);
						}
						if(checkbox8.isSelected()) {
							generateSampleByFormula(new GeneratePolicy(8), "后5分之一下移5倍后的样本数据", amplitude, omega, phase, b);
						}
						if(checkbox9.isSelected()) {
							generateSampleByFormula(new GeneratePolicy(9), "前5分之一上移2倍后的样本数据", amplitude, omega, phase, b);
						}
						if(checkbox10.isSelected()) {
							generateSampleByFormula(new GeneratePolicy(10), "前5分之一上移5倍后的样本数据", amplitude, omega, phase, b);
						}
						if(checkbox11.isSelected()) {
							generateSampleByFormula(new GeneratePolicy(11), "前5分之一下移2倍后的样本数据", amplitude, omega, phase, b);
						}
						if(checkbox12.isSelected()) {
							generateSampleByFormula(new GeneratePolicy(12), "前5分之一下移5倍后的样本数据", amplitude, omega, phase, b);
						}
						if(checkbox13.isSelected()) {
							generateSampleByFormula(new GeneratePolicy(13), "整体振幅扩大2倍后的样本数据", amplitude, omega, phase, b);
						}
						if(checkbox14.isSelected()) {
							generateSampleByFormula(new GeneratePolicy(14), "整体振幅缩小2倍后的样本数据", amplitude, omega, phase, b);
						}
						if(checkbox15.isSelected()) {
							generateSampleByFormula(new GeneratePolicy(15), "前5分之一振幅扩大2倍后的样本数据", amplitude, omega, phase, b);
						}
						if(checkbox16.isSelected()) {
							generateSampleByFormula(new GeneratePolicy(16), "前5分之一振幅缩小2倍后的样本数据", amplitude, omega, phase, b);
						}
						CandyToaster.show(MainWindow.this, "生成样本成功！", CandyToaster.SUCCESS);
					}
					
					@Override
					protected void done() {
						if(candyLoadingBarDialog != null) {
							candyLoadingBarDialog.setVisible(false);
							candyLoadingBarDialog = null;
						}
					}
					
					//根据参数代入公式产生样本保存到TXT文本中
					private void generateSampleByFormula(GeneratePolicy policy, String fileName, double amplitude, double omega, double phase, double b) {
						FileOutputStream fos = null;
						try {
							fos = new FileOutputStream(savePath + "/" + fileName + ".xlsx");
							//[2]将正常样本数据保存到Excel表格中，
							//注意：正常样本数据条数必须跟待测样本数据条数保持一致，如果正常样本数据条数小于待测样本数据条数，剩下的部分用0补齐。
							// 创建workbook
							XSSFWorkbook workbook = new XSSFWorkbook();
							// 加入Worksheet（不加入sheet时生成的xls文件打开时会报错)
							Sheet sheet = workbook.createSheet("训练样本");
							
							ArrayList<Double> dataList = generateDatas(policy.type, amplitude, omega, phase, b);
							// 新建文件
							for(int i = 0; i < rowCount; i++) {
								Row row = sheet.createRow(i);
								Cell cell0 = row.createCell(0);
								cell0.setCellValue(i);
								Cell cell1 = row.createCell(1);
								cell1.setCellValue(dataList.get(i));
							}
							workbook.write(fos);
						} catch (IOException e) {
							e.printStackTrace();
						} finally {
							if(fos != null) {
								try {
									fos.close();
								} catch (IOException e) {
									e.printStackTrace();
								}
							}
						}
					}
					
					//产生数据
					private ArrayList<Double> generateDatas(int type, double amplitude, double omega, double phase, double b) {
						ArrayList<Double> dataList = new ArrayList<Double>();
						switch(type) {
							//原样本数据
							case 0: {
								for(int i = 0; i < rowCount; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b);
								}
								break;
							}
							//整体上移2倍后的样本数据
							case 1: {
								for(int i = 0; i < rowCount; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b + amplitude * 2 * 2);
								}
								break;
							}
							//整体上移5倍后的样本数据
							case 2: {
								for(int i = 0; i < rowCount; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b + amplitude * 2 * 5);
								}
								break;
							}
							//整体下移2倍后的样本数据
							case 3: {
								for(int i = 0; i < rowCount; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b - amplitude * 2 * 2);
								}
								break;
							}
							//整体下移5倍后的样本数据
							case 4: {
								for(int i = 0; i < rowCount; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b - amplitude * 2 * 5);
								}
								break;
							}
							//后1/5上移2倍后的样本数据
							case 5: {
								int i = 0;
								for(; i < rowCount * 4 / 5; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b);
								}
								for(; i < rowCount; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b + amplitude * 2 * 2);
								}
								break;
							}
							//后1/5上移5倍后的样本数据
							case 6: {
								int i = 0;
								for(; i < rowCount * 4 / 5; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b);
								}
								for(; i < rowCount; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b + amplitude * 2 * 5);
								}
								break;
							}
							//后1/5下移2倍后的样本数据
							case 7: {
								int i = 0;
								for(; i < rowCount * 4 / 5; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b);
								}
								for(; i < rowCount; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b - amplitude * 2 * 2);
								}
								break;
							}
							//后1/5下移5倍后的样本数据
							case 8: {
								int i = 0;
								for(; i < rowCount * 4 / 5; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b);
								}
								for(; i < rowCount; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b - amplitude * 2 * 5);
								}
								break;
							}
							//前1/5上移2倍后的样本数据
							case 9: {
								int i = 0;
								for(; i < rowCount / 5; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b + amplitude * 2 * 2);
								}
								for(; i < rowCount; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b);
								}
								break;
							}
							//前1/5上移5倍后的样本数据
							case 10: {
								int i = 0;
								for(; i < rowCount / 5; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b + amplitude * 2 * 5);
								}
								for(; i < rowCount; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b);
								}
								break;
							}
							//前1/5下移2倍后的样本数据
							case 11: {
								int i = 0;
								for(; i < rowCount / 5; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b - amplitude * 2 * 2);
								}
								for(; i < rowCount; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b);
								}
								break;
							}
							//前1/5下移5倍后的样本数据
							case 12: {
								int i = 0;
								for(; i < rowCount / 5; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b - amplitude * 2 * 5);
								}
								for(; i < rowCount; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b);
								}
								break;
							}
							//整体振幅扩大2倍后的样本数据
							case 13: {
								for(int i = 0; i < rowCount; i++) {
									dataList.add(2 * amplitude * Math.sin(omega * (i + phase)) + b);
								}
								break;
							}
							//整体振幅缩小2倍后的样本数据
							case 14: {
								for(int i = 0; i < rowCount; i++) {
									dataList.add(amplitude / 2 * Math.sin(omega * (i + phase)) + b);
								}
								break;
							}
							//前1/5振幅扩大2倍后的样本数据
							case 15: {
								int i = 0;
								for(; i < rowCount / 5; i++) {
									dataList.add(2 * amplitude * Math.sin(omega * (i + phase)) + b);
								}
								for(; i < rowCount; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b);
								}
								break;
							}
							//前1/5振幅缩小2倍后的样本数据
							case 16: {
								int i = 0;
								for(; i < rowCount / 5; i++) {
									dataList.add(amplitude / 2 * Math.sin(omega * (i + phase)) + b);
								}
								for(; i < rowCount; i++) {
									dataList.add(amplitude * Math.sin(omega * (i + phase)) + b);
								}
								break;
							}
						}
						
						return dataList;
					}
					
					//校验文本框是否有空的情况
					private boolean checkTextField(JTextField ...fields) {
						for(JTextField field : fields) {
							if(field.getText().length() == 0) {
								return false;
							}
						}
						return true;
					}
				}.start();
				candyLoadingBarDialog = new CandyLoadingBarDialog(MainWindow.this);
				candyLoadingBarDialog.exec();
			}
		});
		button.setFont(new Font("宋体", Font.PLAIN, 20));
		button.setBounds(162, 477, 116, 46);
		button.setUI(new BEButtonUI().setNormalColor(NormalColor.green));
		button.setForeground(Color.white);
		imageView.add(button);
		
		JLabel lblNewLabel = new JLabel("作者：糖果墙");
		lblNewLabel.setForeground(new Color(123, 104, 238));
		lblNewLabel.setBounds(296, 488, 80, 28);
		//lblNewLabel.setOpaque(true);
		imageView.add(lblNewLabel);
		
		checkbox1 = new JCheckBox("整体上移2倍");
		checkbox1.setSelected(true);
		checkbox1.setBounds(19, 300, 97, 23);
		imageView.add(checkbox1);
		
		checkbox5 = new JCheckBox("后1/5上移2倍");
		checkbox5.setSelected(true);
		checkbox5.setBounds(19, 337, 97, 23);
		imageView.add(checkbox5);
		
		checkbox9 = new JCheckBox("前1/5上移2倍");
		checkbox9.setSelected(true);
		checkbox9.setBounds(19, 377, 97, 23);
		imageView.add(checkbox9);
		
		checkbox2 = new JCheckBox("整体上移5倍");
		checkbox2.setSelected(true);
		checkbox2.setBounds(150, 300, 97, 23);
		imageView.add(checkbox2);
		
		checkbox6 = new JCheckBox("后1/5上移5倍");
		checkbox6.setSelected(true);
		checkbox6.setBounds(150, 337, 97, 23);
		imageView.add(checkbox6);
		
		checkbox10 = new JCheckBox("前1/5上移5倍");
		checkbox10.setSelected(true);
		checkbox10.setBounds(150, 377, 104, 23);
		imageView.add(checkbox10);
		
		checkbox3 = new JCheckBox("整体下移2倍");
		checkbox3.setSelected(true);
		checkbox3.setBounds(274, 300, 104, 23);
		imageView.add(checkbox3);
		
		checkbox4 = new JCheckBox("整体下移5倍");
		checkbox4.setSelected(true);
		checkbox4.setBounds(410, 300, 104, 23);
		imageView.add(checkbox4);
		
		checkbox7 = new JCheckBox("前1/5下移2倍");
		checkbox7.setSelected(true);
		checkbox7.setBounds(274, 337, 104, 23);
		imageView.add(checkbox7);
		
		checkbox8 = new JCheckBox("前1/5下移5倍");
		checkbox8.setSelected(true);
		checkbox8.setBounds(410, 337, 104, 23);
		imageView.add(checkbox8);
		
		checkbox11 = new JCheckBox("后1/5下移2倍");
		checkbox11.setSelected(true);
		checkbox11.setBounds(274, 377, 104, 23);
		imageView.add(checkbox11);
		
		checkbox12 = new JCheckBox("后1/5下移5倍");
		checkbox12.setSelected(true);
		checkbox12.setBounds(410, 377, 104, 23);
		imageView.add(checkbox12);
		
		JLabel lblNewLabel_1 = new JLabel("请选择要生成的样本（基于原始样本的变种样本）：");
		lblNewLabel_1.setForeground(new Color(210, 105, 30));
		lblNewLabel_1.setFont(new Font("宋体", Font.PLAIN, 14));
		lblNewLabel_1.setBounds(36, 259, 327, 35);
		imageView.add(lblNewLabel_1);
		
		checkbox13 = new JCheckBox("整体振幅扩大两倍");
		checkbox13.setSelected(true);
		checkbox13.setBounds(19, 422, 129, 23);
		imageView.add(checkbox13);
		
		checkbox15 = new JCheckBox("前1/5振幅扩大两倍");
		checkbox15.setSelected(true);
		checkbox15.setBounds(274, 422, 129, 23);
		imageView.add(checkbox15);
		
		checkbox14 = new JCheckBox("整体振幅缩小两倍");
		checkbox14.setSelected(true);
		checkbox14.setBounds(150, 422, 129, 23);
		imageView.add(checkbox14);
		
		checkbox16 = new JCheckBox("前1/5振幅缩小两倍");
		checkbox16.setSelected(true);
		checkbox16.setBounds(410, 422, 129, 23);
		imageView.add(checkbox16);
		
		//初始化窗体
		initialFrame();
	}
	
	public void initialFrame() {   //设置窗体的标题、大小及其可见性
		setIconImage(new ImageIcon(IconUtils.getIcon(IconUtils.TITLE_ICON)).getImage());
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(559, 589);
		setLocationRelativeTo(null);
		setResizable(false);
		setVisible(true);
	}
	
	//数据产生策略：等待后期优化
	private class GeneratePolicy {
		private int type = 1;
		public GeneratePolicy(int type) {
			this.type = type;
		}
	}
}
